﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TSites.Service.Common.Utils
{
	public class NumberToStringReader
	{
		private static string[] ChuSo = new string[10] { " không", " một", " hai", " ba", " bốn", " năm", " sáu", " bảy", " tám", " chín" };
		private static string[] Tien = new string[6] { string.Empty, " nghìn", " triệu", " tỉ", " nghìn tỉ", " triệu tỉ" };

		#region Read Number ==> Text

		public static string DocTienBangChu(long SoTien, string strTail)
		{
			try
			{
				int lan, i;
				long so;
				string KetQua = "", tmp = "";
				int[] ViTri = new int[6];
				if (SoTien < 0) return "Số tiền âm!";
				if (SoTien == 0) return "Không đồng!";
				if (SoTien > 0)
				{
					so = SoTien;
				}
				else
				{
					so = -SoTien;
				}

				//Ki?m tra s? quá l?n
				if (SoTien > 8999999999999999)
				{
					SoTien = 0;
					return "";
				}

				ViTri[5] = (int)(so / 1000000000000000);
				so = so - long.Parse(ViTri[5].ToString()) * 1000000000000000;
				ViTri[4] = (int)(so / 1000000000000);
				so = so - long.Parse(ViTri[4].ToString()) * +1000000000000;
				ViTri[3] = (int)(so / 1000000000);
				so = so - long.Parse(ViTri[3].ToString()) * 1000000000;
				ViTri[2] = (int)(so / 1000000);
				ViTri[1] = (int)((so % 1000000) / 1000);
				ViTri[0] = (int)(so % 1000);
				if (ViTri[5] > 0)
				{
					lan = 5;
				}
				else if (ViTri[4] > 0)
				{
					lan = 4;
				}
				else if (ViTri[3] > 0)
				{
					lan = 3;
				}
				else if (ViTri[2] > 0)
				{
					lan = 2;
				}
				else if (ViTri[1] > 0)
				{
					lan = 1;
				}
				else
				{
					lan = 0;
				}

				for (i = lan; i >= 0; i--)
				{
					tmp = DocSo3ChuSo(ViTri[i]);
					KetQua += tmp;
					if (ViTri[i] != 0) KetQua += Tien[i];
					if ((i > 0) && (!string.IsNullOrEmpty(tmp))) KetQua += ",";//&& (!string.IsNullOrEmpty(tmp))
				}

				if (KetQua.Substring(KetQua.Length - 1, 1) == ",")
				{
					KetQua = KetQua.Substring(0, KetQua.Length - 1);
				}
				KetQua = KetQua.Trim() + strTail;
				return KetQua.Substring(0, 1).ToUpper() + KetQua.Substring(1);
			}
			catch (Exception)
			{
				throw;
			}
		}
		#endregion

		#region Read Number(three number) ==> Text

		private static string DocSo3ChuSo(int baso)
		{
			int tram, chuc, donvi;
			string KetQua = "";
			tram = (int)(baso / 100);
			chuc = (int)((baso % 100) / 10);
			donvi = baso % 10;
			if ((tram == 0) && (chuc == 0) && (donvi == 0)) return "";
			if (tram != 0)
			{
				KetQua += ChuSo[tram] + " trăm";
				if ((chuc == 0) && (donvi != 0)) KetQua += " linh";
			}
			if ((chuc != 0) && (chuc != 1))
			{
				KetQua += ChuSo[chuc] + " mươi";
				if ((chuc == 0) && (donvi != 0)) KetQua = KetQua + " linh";
			}
			if (chuc == 1) KetQua += " mười";
			switch (donvi)
			{
				case 1:
					if ((chuc != 0) && (chuc != 1))
					{
						KetQua += " mốt";
					}
					else
					{
						KetQua += ChuSo[donvi];
					}
					break;
				case 5:
					if (chuc == 0)
					{
						KetQua += ChuSo[donvi];
					}
					else
					{
						KetQua += " lăm";
					}
					break;
				default:
					if (donvi != 0)
					{
						KetQua += ChuSo[donvi];
					}
					break;
			}
			return KetQua;
		}

		#endregion

		#region English

		public static string ChangeNumericToWords(double numb)
		{
			string num = numb.ToString();
			return ChangeToWords(num, false);
		}

		public string ChangeCurrencyToWords(string numb)
		{
			return ChangeToWords(numb, true);
		}

		public string ChangeNumericToWords(string numb)
		{
			return ChangeToWords(numb, false);
		}

		public string ChangeCurrencyToWords(double numb)
		{
			return ChangeToWords(numb.ToString(), true);
		}

		private static string ChangeToWords(string numb, bool isCurrency)
		{
			string val = "", wholeNo = numb, points = "", andStr = "", pointStr = "";
			string endStr = (isCurrency) ? ("Only") : ("");
			try
			{
				int decimalPlace = numb.IndexOf(".");
				if (decimalPlace > 0)
				{
					wholeNo = numb.Substring(0, decimalPlace);
					points = numb.Substring(decimalPlace + 1);
					if (Convert.ToInt32(points) > 0)
					{
						andStr = (isCurrency) ? ("and") : ("point");// just to separate whole numbers from points/cents
						endStr = (isCurrency) ? ("Cents " + endStr) : ("");
						pointStr = TranslateCents(points);
					}
				}
				val = String.Format("{0} {1}{2} {3}", TranslateWholeNumber(wholeNo).Trim(), andStr, pointStr, endStr);
			}
			catch { ;}
			return val;
		}

		private static string TranslateWholeNumber(String number)
		{
			string word = "";
			try
			{
				bool beginsZero = false;//tests for 0XX
				bool isDone = false;//test if already translated
				double dblAmt = (Convert.ToDouble(number));
				//if ((dblAmt > 0) && number.StartsWith("0"))
				if (dblAmt > 0)
				{//test for zero or digit zero in a nuemric
					beginsZero = number.StartsWith("0");

					int numDigits = number.Length;
					int pos = 0;//store digit grouping
					String place = "";//digit grouping name:hundres,thousand,etc...
					switch (numDigits)
					{
						case 1://ones' range
							word = Ones(number);
							isDone = true;
							break;
						case 2://tens' range
							word = Tens(number);
							isDone = true;
							break;
						case 3://hundreds' range
							pos = (numDigits % 3) + 1;
							place = " Hundred ";
							break;
						case 4://thousands' range
						case 5:
						case 6:
							pos = (numDigits % 4) + 1;
							place = " Thousand ";
							break;
						case 7://millions' range
						case 8:
						case 9:
							pos = (numDigits % 7) + 1;
							place = " Million ";
							break;
						case 10://Billions's range
							pos = (numDigits % 10) + 1;
							place = " Billion ";
							break;
						//add extra case options for anything above Billion...
						default:
							isDone = true;
							break;
					}
					if (!isDone)
					{//if transalation is not done, continue...(Recursion comes in now!!)
						word = TranslateWholeNumber(number.Substring(0, pos)) + place + TranslateWholeNumber(number.Substring(pos));
						//check for trailing zeros
						if (beginsZero) word = " and " + word.Trim();
					}
					//ignore digit grouping names
					if (word.Trim().Equals(place.Trim())) word = "";
				}
			}
			catch { ;}
			return word.Trim();
		}

		private static string Tens(string digit)
		{
			int digt = Convert.ToInt32(digit);
			String name = null;
			switch (digt)
			{
				case 10:
					name = "Ten";
					break;
				case 11:
					name = "Eleven";
					break;
				case 12:
					name = "Twelve";
					break;
				case 13:
					name = "Thirteen";
					break;
				case 14:
					name = "Fourteen";
					break;
				case 15:
					name = "Fifteen";
					break;
				case 16:
					name = "Sixteen";
					break;
				case 17:
					name = "Seventeen";
					break;
				case 18:
					name = "Eighteen";
					break;
				case 19:
					name = "Nineteen";
					break;
				case 20:
					name = "Twenty";
					break;
				case 30:
					name = "Thirty";
					break;
				case 40:
					name = "Fourty";
					break;
				case 50:
					name = "Fifty";
					break;
				case 60:
					name = "Sixty";
					break;
				case 70:
					name = "Seventy";
					break;
				case 80:
					name = "Eighty";
					break;
				case 90:
					name = "Ninety";
					break;
				default:
					if (digt > 0)
					{
						name = Tens(digit.Substring(0, 1) + "0") + " " + Ones(digit.Substring(1));
					}
					break;
			}
			return name;
		}

		private static string Ones(string digit)
		{
			int digt = Convert.ToInt32(digit);
			String name = "";
			switch (digt)
			{
				case 1:
					name = "One";
					break;
				case 2:
					name = "Two";
					break;
				case 3:
					name = "Three";
					break;
				case 4:
					name = "Four";
					break;
				case 5:
					name = "Five";
					break;
				case 6:
					name = "Six";
					break;
				case 7:
					name = "Seven";
					break;
				case 8:
					name = "Eight";
					break;
				case 9:
					name = "Nine";
					break;
			}
			return name;
		}

		private static string TranslateCents(string cents)
		{
			String cts = "", digit = "", engOne = "";
			for (int i = 0; i < cents.Length; i++)
			{
				digit = cents[i].ToString();
				if (digit.Equals("0"))
				{
					engOne = "Zero";
				}
				else
				{
					engOne = Ones(digit);
				}
				cts += " " + engOne;
			}
			return cts;
		}

		#endregion
	}
}
